package setting

import (
	"crypto/tls"
	"fmt"
	"github.com/spf13/viper"
)

type Cfg struct {
	Application Application
	DbCfg       Database
	Jwt         Jwt
	PluginCfg   PluginCfg
	Secret      Secret
	RedisConfig *RedisConfig
	// GRPC Server.
	GRPCServerNetwork   string
	GRPCServerAddress   string
	GRPCIsAuth          bool
	GRPCServerTLSConfig *tls.Config

	// build
	BuildVersion string
}

type CommandLineArgs struct {
	Config   string
	HomePage string
	Args     []string
}

func NewCfg() *Cfg {
	return &Cfg{}
}

func NewCfgFromArgs(args CommandLineArgs) (*Cfg, error) {
	cfg := NewCfg()
	if err := cfg.Load(args); err != nil {
		return nil, err
	}
	//cfg.BuildVersion = opts.Version
	return cfg, nil
}

func (cfg *Cfg) Load(args CommandLineArgs) error {
	viper := viper.New()
	viper.SetConfigFile(args.Config)
	err := viper.ReadInConfig()
	if err != nil {
		panic(fmt.Sprintf("read setting :%s,err:%s", args.Config, err))
	}
	cfg.loadApplication(viper, args)
	cfg.loadDatabase(viper)
	cfg.loadLogger(viper)
	cfg.loadJwt(viper)
	cfg.readPluginSettings(viper) //加载插件配置
	cfg.initRsaSecret()
	//加载redis配置
	grpc := viper.Sub("grpcServer")
	if grpc != nil {
		cfg.GRPCServerNetwork = grpc.GetString("network")
		cfg.GRPCServerAddress = grpc.GetString("address")
		cfg.GRPCIsAuth = grpc.GetBool("isAuth")
		useTLS := grpc.GetBool("useTLS")
		if useTLS {
			errPrefix := "grpc_server:"
			certFile := grpc.GetString("tlsCertFile")
			certKeyFile := grpc.GetString("tlsKeyFile")
			serverCert, err := tls.LoadX509KeyPair(certFile, certKeyFile)
			if err != nil {
				return fmt.Errorf("%s error loading X509 key pair: %w", errPrefix, err)
			}
			cfg.GRPCServerTLSConfig = &tls.Config{
				Certificates: []tls.Certificate{serverCert},
				ClientAuth:   tls.NoClientCert,
			}
		}
	}
	// 监听配置文件变化
	viper.WatchConfig()
	return nil
}
